package com.Lab427.workflow.utils;

import com.Lab427.workflow.common.enums.NodeType;
import com.Lab427.workflow.common.enums.ParamsType;
import com.Lab427.workflow.entity.WorkflowEdge;
import com.Lab427.workflow.entity.WorkflowNode;
import com.Lab427.workflow.pojo.WorkNode;
import com.Lab427.workflow.service.DAGExecutor.NodeServiceDispatcher;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Yue
 * @date:2025/8/26 19:46
 */
public class WorkFlowUtils {

    /**
     * @author Yue
     * @date:2025/8/26 19:46
     * input:传入有向无环图
     * output：将图解析为workNode
     */
    public static List<WorkNode> convertGraphToWorkNodes(NodeServiceDispatcher dispatcher,
                                                            Map<String, Object> graph) {
        // 从 graph 获取原始实体列表
        List<WorkflowNode> nodes = (List<WorkflowNode>) graph.get("nodes");
        List<WorkflowEdge> edges = (List<WorkflowEdge>) graph.get("edges");

        // 构建 nodeId -> 依赖节点列表
        Map<Long, List<Long>> dependencyMap = new HashMap<>();
        for (WorkflowEdge edge : edges) {
            Long from = edge.getFromNodeId();
            Long to = edge.getToNodeId();
            dependencyMap.computeIfAbsent(to, k -> new ArrayList<>()).add((long) from.intValue());
        }

        List<WorkNode> workNodes = new ArrayList<>();
        for (WorkflowNode node : nodes) {
            Long nodeId = node.getNodeId();
            String name = node.getName();
            String typeStr = node.getType();
            NodeType type = NodeType.valueOf(typeStr.toUpperCase()); // 根据你的 NodeType 枚举
            Map<String,Object> config = node.getConfig();
            List<Long> dependencies = dependencyMap.getOrDefault(nodeId, new ArrayList<>());

            WorkNode workNode = new WorkNode(dispatcher,
                    nodeId,
                    name,
                    type,
                    config,
                    dependencies);
            workNodes.add(workNode);
        }

        return workNodes;
    }
    /**
     * @author Yue
     * @date:2025/8/27 15:46
     * input:所有的worknode
     * output：将图解析为workNode
     */
    public static List<List<WorkNode>> batchTopologicalSort(List<WorkNode> workNodes) {
        // 1. 构建 nodeId -> WorkNode 映射
        Map<Long, WorkNode> nodeMap = workNodes.stream()
                .collect(Collectors.toMap(WorkNode::getId, w -> w));

        // 2. 统计每个节点的入度（依赖数量）
        Map<Long, Integer> inDegree = new HashMap<>();
        for (WorkNode node : workNodes) {
            inDegree.put(node.getId(), node.getDependencies().size());
        }

        List<List<WorkNode>> batches = new ArrayList<>();
        Set<Long> executed = new HashSet<>();

        while (executed.size() < workNodes.size()) {
            // 找到入度为0且未执行的节点
            List<WorkNode> batch = workNodes.stream()
                    .filter(n -> !executed.contains(n.getId()) && inDegree.get(n.getId()) == 0)
                    .collect(Collectors.toList());

            if (batch.isEmpty()) {
                throw new RuntimeException("存在循环依赖，无法排序！");
            }

            // 添加到当前批次
            batches.add(batch);

            // 更新入度：执行完 batch 后，依赖它们的节点入度减1
            for (WorkNode node : batch) {
                executed.add(node.getId());
                for (WorkNode next : workNodes) {
                    System.out.println(node.getId());
                    System.out.println(next.getDependencies());
                    if (next.getDependencies().contains(node.getId())) {
                        inDegree.put(next.getId(), inDegree.get(next.getId()) - 1);
                    }
                }
            }
        }

        return batches;
    }

    /**
     * 将上一批节点执行的返回结果注入到下一批节点的 config 中
     * @param nextBatch 下一批待执行的节点
     * @param previousResults 已完成节点的返回值，key=nodeId, value=返回结果
     */
    public static void injectPreviousResults(List<WorkNode> nextBatch, Map<Long, String> previousResults) {
        for (WorkNode node : nextBatch) {
            // 保留原有 config
            Map<String, Object> config = node.getConfig();
            if (config == null) {
                config = new HashMap<>();
                node.setConfig(config);
            }

            // 获取现有 outputData 或创建新 Map
            Map<String, Object> outputData = new HashMap<>();

            // 遍历当前节点依赖，将依赖节点返回值加入 outputData
            for (Long depId : node.getDependencies()) {
                String depResult = previousResults.get(depId);
                if (depResult != null) {
                    outputData.put("outputData"+depId, depResult);
                }
            }
            config.put(ParamsType.OUTPUT_LASTBATCH.getValue(),outputData);
        }
    }



}
